package web

import (
	"io"
	"net/http"
	"sync"

	"gddgame.cc/galaxy/utils/def"
)

type RouterHandler func(path string) Router

type Engine interface {
	io.Closer
	SetDebug(flag bool)
	Listen() error
	Get(address string) Router
	SetLogger(logger def.Logger)
	Register(address string, fn func(router Router, handler RouterHandler) error) func() error
}

type engine struct {
	logger  def.Logger
	debug   bool
	servers map[string]*httpServer

	pool sync.Pool
}

func NewEngine() Engine {
	e := &engine{
		servers: make(map[string]*httpServer),
		pool:    sync.Pool{},
	}
	e.pool.New = func() interface{} {
		return NewContext()
	}
	return e
}
func (e *engine) SetDebug(flag bool) {
	e.debug = flag
}

// todo 划分域名
func (e *engine) get(address string) *router {
	if server, ok := e.servers[address]; ok {
		return server.router
	}
	server := newServer(e, address, newRouter(e))
	e.servers[address] = server
	return server.router
}
func (e *engine) Get(address string) Router {
	return e.get(address)
}

func (e *engine) Listen() error {
	for k, _ := range e.servers {
		if err := e.servers[k].Listen(); err != nil {
			return err
		}
	}
	return nil
}

func (e *engine) Close() error {
	for k, _ := range e.servers {
		if err := e.servers[k].Close(); err != nil {
			return err
		}
	}
	return nil
}

func (e *engine) Register(address string, fn func(router Router, handler RouterHandler) error) func() error {
	return func() error {
		r := e.Get(address)
		return fn(r, func(path string) Router {
			rr := r.Group(path)
			e.logger.Debugf("[ Web ] Address: %#v %#v", address, path)
			return rr
		})
	}
}

func (e *engine) Test(address string) http.Handler {
	return e.get(address).router
}

func (e *engine) SetLogger(logger def.Logger) {
	e.logger = logger
}
